
#include "ObjThread.h"
#include "vm.h"

//为运行函数准备桢栈
void ObjThread::PrepareFrame(ObjThread *objThread, ObjClosure *objClosure, Value *stackStart) {
    ASSERT(objThread->frameCapacity > objThread->usedFrameNum, "frame not enough!!");
    //objThread->usedFrameNum是最新可用的frame
    Frame *frame = &(objThread->frames[objThread->usedFrameNum++]);

    //thread中的各个frame是共享thread的stack
    //frame用frame->stackStart指向各自frame在thread->stack中的起始地址
    frame->stackStart = stackStart;
    frame->closure = objClosure;
    frame->ip = objClosure->fn->instrStream.datas;
}

void ObjThread::ResetThread(ObjThread *objThread, ObjClosure *objClosure) {
    objThread->esp = objThread->stack;
    objThread->openUpvalues = NULL;
    objThread->caller = NULL;
    objThread->errorObj = VT_TO_VALUE(VT_NULL);
    objThread->usedFrameNum = 0;

    ASSERT(objClosure != NULL, "objClosure is NULL in function resetThread");
    ObjThread::PrepareFrame(objThread, objClosure, objThread->stack);
}


ObjThread *ObjThread::NewObjThread(VM *vm, ObjClosure *objClosure) {
    ASSERT(objClosure != NULL, "objClosure is NULL!");

    Frame *frames = ALLOCATE_ARRAY(vm, Frame, INITIAL_FRAME_NUM);

    //加1是为接收者的slot
    uint32_t stackCapacity = ceilToPowerOf2(objClosure->fn->maxStackSlotUsedNum + 1);
    Value *newStack = ALLOCATE_ARRAY(vm, Value, stackCapacity);

    auto *objThread = ALLOCATE(vm, ObjThread);
    objThread->objHeader = *new ObjHeader(vm, OT_THREAD, vm->threadClass);
    objThread->frames = frames;
    objThread->frameCapacity = INITIAL_FRAME_NUM;
    objThread->stack = newStack;
    objThread->stackCapacity = stackCapacity;

    ResetThread(objThread, objClosure);
    return objThread;
}

ObjThread::ObjThread(VM *vm, ObjClosure *objClosure) {
    ASSERT(objClosure != NULL, "objClosure is NULL!");

    Frame *frames = ALLOCATE_ARRAY(vm, Frame, INITIAL_FRAME_NUM);

    //加1是为接收者的slot
    uint32_t stackCapacity = ceilToPowerOf2(objClosure->fn->maxStackSlotUsedNum + 1);
    Value *newStack = ALLOCATE_ARRAY(vm, Value, stackCapacity);

    auto *objThread = ALLOCATE(vm, ObjThread);
    objThread->objHeader = *new ObjHeader(vm, OT_THREAD, vm->threadClass);
    objThread->frames = frames;
    objThread->frameCapacity = INITIAL_FRAME_NUM;
    objThread->stack = newStack;
    objThread->stackCapacity = stackCapacity;

    ResetThread(objThread, objClosure);

    this->stack = objThread->stack;
    this->frames = objThread->frames;
    this->objHeader = objThread->objHeader;
    this->stackCapacity = objThread->stackCapacity;
    this->usedFrameNum = objThread->usedFrameNum;
    this->frameCapacity = objThread->frameCapacity;
    this->caller = objThread->caller;
    this->errorObj = objThread->errorObj;
    this->esp = objThread->esp;
    this->openUpvalues = objThread->openUpvalues;

}



